package com.hcms.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hcms.admin.dto.CmsCateOptionResponse;
import com.hcms.admin.dto.CmsCateTreeResponse;
import com.hcms.admin.service.ICmsCateService;
import com.hcms.common.exception.ApiException;
import com.hcms.common.util.TreeUtil;
import com.hcms.mybatis.dto.CmsCateOption;
import com.hcms.mybatis.entity.CmsCate;
import com.hcms.mybatis.mapper.CmsCateMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 栏目管理 服务实现类
 * </p>
 *
 * @author achenxw@126.com
 * @since 2023-03-31
 */
@Service
public class CmsCateServiceImpl extends ServiceImpl<CmsCateMapper, CmsCate> implements ICmsCateService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private CmsCateMapper cmsCateMapper;

    @Override
    public List<CmsCateTreeResponse> getTreeList() {
        logger.info("Run getTreeList()");
        LambdaQueryWrapper<CmsCate> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByAsc(CmsCate::getSort, CmsCate::getId);
        List<CmsCate> cmsCates = cmsCateMapper.selectList(queryWrapper);
        List<CmsCateTreeResponse> results = cmsCates.stream().map(CmsCateTreeResponse::new).collect(Collectors.toList());
        return TreeUtil.builder(results, 0L);
    }

    @Override
    public List<CmsCateOptionResponse> getOptions() {
        logger.info("Run getOptions()");
        List<CmsCateOption> options = cmsCateMapper.getOptions();
        List<CmsCateOptionResponse> results = options.stream().map(CmsCateOptionResponse::new).collect(Collectors.toList());
        return TreeUtil.builder(results, 0L);
    }

    @Override
    public List<CmsCate> selectChildrenCate(Long parentId) {
        return cmsCateMapper.selectChildrenCate(parentId);
    }

    @Override
    public CmsCate getView(Long id) {
        logger.info("Run getView()");
        return cmsCateMapper.selectById(id);
    }

    @Override
    public int createItem(CmsCate entity) {
        logger.info("Run createItem()");
        //获取父级记录数据
        entity.setId(null);
        entity.setIdList(getIdList(entity.getParentId()));
        entity.setCreateTime(new Date());
        return cmsCateMapper.insert(entity);
    }

    @Override
    public int updateItem(Long id, CmsCate entity) {
        logger.info("Run updateItem(), id={}", id);
        //校验parentId，防止脏数据
        checkParentId(id, entity.getParentId());
        entity.setId(id);
        entity.setIdList(getIdList(entity.getParentId()));
        int count = cmsCateMapper.updateById(entity);
        if (count > 0) {
            //更新子记录的idList字段
            updateChildrenIdList(entity);
        }
        return count;
    }

    @Override
    public int deleteItem(String ids) {
        logger.info("Run deleteItem, ids={}", ids);
        String[] split = ids.split(",");
        List<String> list = Arrays.asList(split);
        List<Long> delIds = list.stream().map(Long::new).collect(Collectors.toList());
        //评断是否有子记录
        LambdaQueryWrapper<CmsCate> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(CmsCate::getParentId, delIds);
        List<CmsCate> sysCates = cmsCateMapper.selectList(queryWrapper);
        if (sysCates.size() > 0) {
            logger.error("A child record cannot be deleted");
            throw new ApiException("有子记录不可删除");
        }
        return cmsCateMapper.deleteBatchIds(delIds);
    }

    /**
     * 根据 parentId 生成 idList
     */
    private String getIdList(Long parentId) {
        logger.info("Run getIdList(), parentId={}", parentId);
        String idList;
        if (parentId > 0) {
            CmsCate parentCate = getView(parentId);
            if (parentCate != null) {
                idList = parentCate.getIdList() + "," + parentCate.getId();
            } else {
                logger.error("The parent record does not exist");
                throw new ApiException("父级记录不存在");
            }
        } else {
            idList = "0";
        }
        return idList;
    }

    /**
     * 更新子记录的idList字段
     */
    private void updateChildrenIdList(CmsCate parentCate) {
        LambdaQueryWrapper<CmsCate> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CmsCate::getParentId, parentCate.getId());
        List<CmsCate> children = cmsCateMapper.selectList(queryWrapper);
        for (CmsCate child : children) {
            String idList = parentCate.getIdList() + "," + parentCate.getId();
            if (!idList.equals(child.getIdList())) {
                child.setIdList(idList);
                int count = cmsCateMapper.updateById(child);
                if (count > 0) {
                    updateChildrenIdList(child);
                }
            }
        }
    }

    /**
     * 校验parentId层级关系，防止脏数据
     */
    private void checkParentId(Long id, Long parentId) {
        logger.info("Run checkParentId(), id={}, parentId={}", id, parentId);
        List<CmsCate> childrenCate = cmsCateMapper.selectChildrenCate(id);
        List<Long> idsList = childrenCate.stream().map(CmsCate::getId).collect(Collectors.toList());
        if (id.equals(parentId) || idsList.contains(parentId)) {
            logger.error("The parent-child field hierarchy is incorrect");
            throw new ApiException("父子字段层级关系错误");
        }
    }

}
